package com.ideaction.game.utils;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

/**
 * 处理json的工具类
 *
 * @author Ray
 */
@Slf4j
public class JsonUtils {
    private static ObjectMapper mapper = new ObjectMapper();

    static {
        //忽略空Bean转json的错误
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,false);
        //忽略 在json字符串中存在，但是在java对象中不存在对应属性的情况。防止错误
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * JSON字符串 转 POJO
     */
    public static <T> T parseObject(String pojo, Class<T> tClass) {
        if (StringUtils.isEmpty(pojo)) {
            return null;
        }
        try {
            return mapper.readValue(pojo, tClass);
        } catch (Exception e) {
            log.error("json String to object fail. jsonString=" + pojo + ", class=" + tClass, e);
        }
        return null;
    }
    
    /**
     * JSON字符串 转 POJO
     */
    public static <T> T parseObject(File file, Class<T> tClass) {
        if (file == null || !file.exists() || !file.isFile()) {
            return null;
        }
        try {
            return mapper.readValue(file, tClass);
        } catch (Exception e) {
            log.error("json String to object fail. fileName=" + file.getName() + ", class=" + tClass, e);
        }
        return null;
    }
    
    /**
     * JSON字符串 转 POJO
     */
    public static <T> T parseObject(InputStream in, Class<T> tClass) {
        if (in == null) {
            return null;
        }
        try {
            return mapper.readValue(in, tClass);
        } catch (Exception e) {
            log.error("json String to object fail. class=" + tClass, e);
        }
        return null;
    }

    /**
     * JSON字符串 转 POJO
     */
    public static <T> T parseObject(byte[] pojo, Class<T> tClass) {
        try {
            return mapper.readValue(pojo, tClass);
        } catch (Exception e) {
            log.error("json bytes to object fail. class=" + tClass);
        }
        return null;
    }

    /**
     * pojo 转json
     */
    public static <T> String toJson(T obj) {
        try {
            return mapper.writeValueAsString(obj);
        } catch (Exception e) {
            log.error("object to json fail. class=" + obj.getClass());
        }
        return null;
    }

    /**
     * pojo 转json
     */
    public static <T> byte[] toJsonBytes(T obj) {
        try {
            return mapper.writeValueAsBytes(obj);
        } catch (Exception e) {
            log.error("object to json bytes fail. class=" + obj.getClass());
        }
        return null;
    }

    /**
     * json 转 List<T>
     */
    public static <T> List<T> parseObjectList(String jsonStr, Class<T> tClass) {
        try {
            JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, tClass);
            return mapper.readValue(jsonStr, javaType);
        } catch (Exception e) {
            log.error("json string to object list fail. class=" + tClass);
        }
        return null;
    }

    /**
     * 将json数据转换成Map集合
     *
     * @param jsonData
     *         JSON数据
     * @param keyType
     *         键类型
     * @param valueType
     *         值类型
     * @return Map集合
     */
    public static <K, V> Map<K, V> parseObjectMap(String jsonData, Class<K> keyType, Class<V> valueType) {
        try {
            JavaType javaType = mapper.getTypeFactory().constructMapType(Map.class, keyType, valueType);
            return mapper.readValue(jsonData, javaType);
        } catch (Exception e) {
            log.error("json string to object map fail.");
        }
        return null;
    }
    
    /**
     * 将json数据转换成Map集合
     *
     * @param file
     *         JSON数据
     * @param keyType
     *         键类型
     * @param valueType
     *         值类型
     * @return Map集合
     */
    public static <K, V> Map<K, V> parseObjectMap(File file, Class<K> keyType, Class<V> valueType) {
        if (file == null || !file.exists() || !file.isFile()) {
            return null;
        }
        try {
            JavaType javaType = mapper.getTypeFactory().constructMapType(Map.class, keyType, valueType);
            return mapper.readValue(file, javaType);
        } catch (Exception e) {
            log.error("json string to object map fail.");
        }
        return null;
    }
}
